#ifndef __LIST_H
#define __LIST_H
#include <stdbool.h>
#define offset(type, member) (size_t)(&((type *)0->member))
#define container(addr, type, member) (type *)((void *)(addr) - offset(type, member))

typedef struct _list_node
{
    struct _list_node *prev;
    struct _list_node *next;
    void *data;
}ListNode;

typedef ListNode *ListItr;

typedef struct _list
{
    ListNode *head;
    ListNode *tail;
    int len;
    void (*free)(void *);
    bool (*match)(void*, void*);
}List;

#define list_for_each(node, list) for(node = list->head; node; node = node->next)
#define void2type(data, type) *(type *)(data)

// api
int list_find_node_index(List *list, ListNode *node);
int list_insert_head_node(List *list, ListNode *node);
int list_insert_tail_node(List *list, ListNode *node);
int list_insert_before(List *list, ListNode *pos, ListNode *node);
int list_insert_before_safe(List *list, ListNode *pos, ListNode *node);
ListNode *list_del_head_node(List *list);
ListNode *list_del_tail_node(List *list);
ListNode *list_del_node(List *list, ListNode *node);
ListNode *list_del_node_safe(List *list, ListNode *node);

List *list_new();
void *list_head(List *list);
void *list_tail(List *list);
int list_len(List *list);
int list_insert_head(List *list, void *data);
int list_insert_tail(List *list, void *data);
void *list_del_head(List *list);
void *list_del_tail(List *list);
void list_empty(List *list);
void list_free(List *list);
void *list_get(List *list, int index);
int list_find(List *list, void *data);

void list_print(List *list, void (*print)(void *));
int list_insert_order(List *list, ListNode *node, int (*compare)(void *, void *));

#endif